import { Injectable } from '@nestjs/common';
import { MulterStorageService } from '@/module/file/upload/storage.service';
import { Result } from '@/common/utils/result';
import { join } from 'path';
import { createWriteStream, existsSync, mkdirSync, promises, readdirSync } from 'fs';
import { extname } from 'node:path';
import { Repository } from 'typeorm';
import { Upload } from '@/module/file/upload/entities/upload.entity';
import { UPLOAD_STATUS } from '@/common/enums';
import { InjectRepository } from '@nestjs/typeorm';

@Injectable()
export class UploadService {
  constructor(
    private readonly storageService: MulterStorageService,
    @InjectRepository(Upload) private readonly fileRepo: Repository<Upload>,
  ) {
  }

  async saveFile(file: Express.Multer.File, createBy: string) {
    await this.fileRepo.save({
      fileId: file.filename,
      originalName: file.originalname,
      fileSize: file.size,
      storedName: file.filename,
      status: UPLOAD_STATUS.COMPLETED,
      filePath: file.path,
      createBy: createBy,
      updateBy: createBy,
      totalChunks: 1,
    });
    return Result.ok({
      filename: file.filename,
      path: `/uploads/${file.fieldname}`,
      message: '上传成功',
    });
  }


  async saveChunk(file: Express.Multer.File, fileId: string, chunkIndex: number) {
    const chunkDir = join(this.storageService.getUploadPath(), `chunks_${fileId}`);

    // 确保分片存储目录存在
    if (!existsSync(chunkDir)) {
      mkdirSync(chunkDir);
    }

    // 使用异步方法避免阻塞
    const chunkPath = join(chunkDir, `${chunkIndex}`);
    await promises.rename(file.path, chunkPath);

    return Result.ok({
      message: '分片上传成功',
      chunkIndex,
    });
  }


  async mergeChunks(fileId: string, totalChunks: number, createBy: string) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
    const ext = extname(fileId);
    const filename = `${uniqueSuffix}${ext}`;
    const chunkDir = join(this.storageService.getUploadPath(), `chunks_${fileId}`);
    const finalFilePath = join(this.storageService.getUploadPath(), filename);

    // 检查分片是否完整
    const files = readdirSync(chunkDir)
      .map(name => parseInt(name, 10))
      .filter(num => !isNaN(num))
      .sort((a, b) => a - b); // 确保顺序正确

    if (files.length !== totalChunks) {
      throw new Error(`分片不完整，期望 ${totalChunks} 个，实际 ${files.length} 个`);
    }

    const writeStream = createWriteStream(finalFilePath, { flags: 'a' });

    try {
      // 依次读取每个分片，并追加到最终文件
      for (const chunkIndex of files) {
        const chunkPath = join(chunkDir, `${chunkIndex}`);
        const chunkBuffer = await promises.readFile(chunkPath);
        await promises.appendFile(finalFilePath, chunkBuffer);
        await promises.unlink(chunkPath); // 逐步删除分片
      }
    } catch (error) {
      console.error('文件合并失败:', error);
      throw new Error('文件合并失败');
    } finally {
      writeStream.end();
    }

    // 删除临时分片目录
    await promises.rmdir(chunkDir);

    await this.fileRepo.save({
      fileId: filename,
      originalName: fileId,
      fileSize: totalChunks,
      storedName: filename,
      status: UPLOAD_STATUS.COMPLETED,
      totalChunks: totalChunks,
      fileChunkSize: totalChunks,
      filePath: finalFilePath,
      createBy: createBy,
      updateBy: createBy,
    });
    return Result.ok({
      message: '文件合并成功',
      path: finalFilePath,
    });
  }
}
